package exceptions;
class BaseballException extends Exception{}
class Foul extends BaseballException{}
class Strike extends BaseballException{}

abstract class Inning{
    public Inning() throws BaseballException{}
    public void event() throws BaseballException{}
    public abstract void atBat() throws Strike, Foul;
    public void walk(){}
}

class StormException extends Exception{}
class RainedOut extends StormException{}
class PopFoul extends Foul{}

interface Storm{
    public void event() throws RainedOut;
    public void rainHard() throws RainedOut;
}

public class StormyInning extends Inning implements Storm{
    // Ok to add new exceptions fof constructors, but
    // you must deal with the base constructor exceptions
    public StormyInning() throws RainedOut, BaseballException{}

    public StormyInning(String s) throws Fourl, BaseballException{}

    // Regular methods must conform to base class:
    // ! void walk throws PopFoul{}//Compile error
    // Interface CANNOT add exceptions to existing
    // method from the vase class:
    // ! public void event() throws RainedOut{}
    // If the method doesn't already exist in the 
    // base class, the exception is ok:
    public void rainHard() throws RainedOut{}
    // You can choose to not throw any exceptions
    // even if the base version does:
    public void event(){}
    // Overridden methods can throw inherited exceptions
    public void atBat() throws PopFoul{}
    public static void main(String[] args){
        try{
            StormyInning si = new StormyInning();
            si.atBat();
        }catch(PopFoul e){
            System.out.println("Pop foul");
        }catch(RainFoul e){
            System.out.println("Rained out");
        }catch(BaseballException e){
            System.out.println("Generic baseball exception");
        }

        // Strike not thrown in derived version
        try{
            // What happens if you upcast
            Inning i = new StormyInning();
            i.atBat();
        }catch(Strike e){
            System.out.println("Strike");
        }catch(Fourl e ){
            System.out.println("Foul");
        }catch(RainedOut e){
            System.out.println("Rained out");
        }catch(BaseballException e){
            System.out.println("Generic baseball exception");
        }
    }
}
